package com.jsh.erp.service.retailRecord;

import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.toolkit.StringUtils;
import com.jsh.erp.constants.BusinessConstants;
import com.jsh.erp.constants.ExceptionConstants;
import com.jsh.erp.datasource.entities.*;
import com.jsh.erp.datasource.mappers.CashBoxRecordMapper;
import com.jsh.erp.datasource.mappers.MaterialCategoryMapper;
import com.jsh.erp.datasource.mappers.RetailRecordMapperEx;
import com.jsh.erp.datasource.mappers.RetailRecordMapper;
import com.jsh.erp.exception.BusinessRunTimeException;
import com.jsh.erp.service.depotHead.DepotHeadService;
import com.jsh.erp.service.log.LogService;
import com.jsh.erp.service.materialCategory.MaterialCategoryService;
import com.jsh.erp.service.redis.RedisService;
import com.jsh.erp.service.systemConfig.SystemConfigService;
import com.jsh.erp.service.user.UserService;
import com.jsh.erp.utils.IdUtils;
import com.jsh.erp.utils.StringUtil;
import com.jsh.erp.utils.Tools;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import java.math.BigDecimal;
import java.util.*;

import static com.jsh.erp.utils.Tools.getCenternTime;

@Service
public class RetailRecordService {
    private Logger logger = LoggerFactory.getLogger(RetailRecordService.class);
    @Resource
    private RetailRecordMapper retailRecordMapper;

    @Resource
    private RetailRecordMapperEx retailRecordMapperEx;

    @Resource
    private CashBoxRecordMapper cashBoxRecordMapper;

    @Resource
    private UserService userService;

    @Resource
    private LogService logService;

    @Resource
    private RedisService redisService;
    @Resource
    private MaterialCategoryMapper materialCategoryMapper;
    @Resource
    private SystemConfigService systemConfigService;


    public RetailRecord getRetailRecord(String id) throws Exception {
        RetailRecord result = null;
        String lanCode = systemConfigService.getLanCode();
        try {
            result = retailRecordMapper.selectByPrimaryKey(id);
        } catch (Exception e) {
            logger.error("异常码[{}],异常提示[{}],异常[{}]",
                    ExceptionConstants.DATA_READ_FAIL_CODE, "zh".equals(lanCode) ? ExceptionConstants.DATA_READ_FAIL_MSG : ExceptionConstants.DATA_READ_FAIL_MSG_US, e);
            throw new BusinessRunTimeException(ExceptionConstants.DATA_READ_FAIL_CODE,
                    "zh".equals(lanCode) ? ExceptionConstants.DATA_READ_FAIL_MSG : ExceptionConstants.DATA_READ_FAIL_MSG_US);
        }
        return result;
    }

    public List<RetailRecord> getRetailRecord() throws Exception {
        RetailRecordExample example = new RetailRecordExample();
        example.createCriteria().andDeleteFlagNotEqualTo(BusinessConstants.DELETE_FLAG_DELETED);
        List<RetailRecord> list = null;
        String lanCode = systemConfigService.getLanCode();
        try {
            list = retailRecordMapper.selectByExample(example);
        } catch (Exception e) {
            logger.error("异常码[{}],异常提示[{}],异常[{}]",
                    ExceptionConstants.DATA_READ_FAIL_CODE, "zh".equals(lanCode) ? ExceptionConstants.DATA_READ_FAIL_MSG : ExceptionConstants.DATA_READ_FAIL_MSG_US, e);
            throw new BusinessRunTimeException(ExceptionConstants.DATA_READ_FAIL_CODE,
                    "zh".equals(lanCode) ? ExceptionConstants.DATA_READ_FAIL_MSG : ExceptionConstants.DATA_READ_FAIL_MSG_US);
        }
        return list;
    }

    public List<RetailRecordEx> select(int offset, int rows) throws Exception {
        List<RetailRecordEx> list = null;
        String lanCode = systemConfigService.getLanCode();
        try {
            list = retailRecordMapperEx.select(offset, rows);
        } catch (Exception e) {
            logger.error("异常码[{}],异常提示[{}],异常[{}]",
                    ExceptionConstants.DATA_READ_FAIL_CODE, "zh".equals(lanCode) ? ExceptionConstants.DATA_READ_FAIL_MSG : ExceptionConstants.DATA_READ_FAIL_MSG_US, e);
            throw new BusinessRunTimeException(ExceptionConstants.DATA_READ_FAIL_CODE,
                    "zh".equals(lanCode) ? ExceptionConstants.DATA_READ_FAIL_MSG : ExceptionConstants.DATA_READ_FAIL_MSG_US);
        }
        return list;
    }

    public Long countRetailRecord() throws Exception {
        Long result = null;
        String lanCode = systemConfigService.getLanCode();
        try {
            User userInfo = userService.getCurrentUser();
            if (!BusinessConstants.DEFAULT_MANAGER.equals(userInfo.getLoginName())) {
                result = retailRecordMapperEx.counts();
            }
        } catch (Exception e) {
            logger.error("异常码[{}],异常提示[{}],异常[{}]",
                    ExceptionConstants.DATA_READ_FAIL_CODE, "zh".equals(lanCode) ? ExceptionConstants.DATA_READ_FAIL_MSG : ExceptionConstants.DATA_READ_FAIL_MSG_US, e);
            throw new BusinessRunTimeException(ExceptionConstants.DATA_READ_FAIL_CODE,
                    "zh".equals(lanCode) ? ExceptionConstants.DATA_READ_FAIL_MSG : ExceptionConstants.DATA_READ_FAIL_MSG_US);
        }
        return result;
    }

    @Transactional(value = "transactionManager", rollbackFor = Exception.class)
    public int insertRetailRecord(JSONObject obj, HttpServletRequest request) throws Exception {
        RetailRecord retailRecord = JSONObject.parseObject(obj.toJSONString(), RetailRecord.class);
        retailRecord.setId(IdUtils.getUUID());
        retailRecord.setUploadFlag("0");
        String lanCode = systemConfigService.getLanCode();
        int result = 0;
        try {
            User userInfo = userService.getCurrentUser();
            if (!BusinessConstants.DEFAULT_MANAGER.equals(userInfo.getLoginName())) {
                result = retailRecordMapper.insertSelective(retailRecord);
                logService.insertLog("收银员上班",
                        new StringBuffer(BusinessConstants.LOG_OPERATION_TYPE_EDIT).append(retailRecord.getStartTime()).toString(), request);
            }
        } catch (Exception e) {
            logger.error("异常码[{}],异常提示[{}],异常[{}]",
                    ExceptionConstants.DATA_WRITE_FAIL_CODE, "zh".equals(lanCode) ? ExceptionConstants.DATA_WRITE_FAIL_MSG : ExceptionConstants.DATA_WRITE_FAIL_MSG_US, e);
            throw new BusinessRunTimeException(ExceptionConstants.DATA_WRITE_FAIL_CODE,
                    "zh".equals(lanCode) ? ExceptionConstants.DATA_WRITE_FAIL_MSG : ExceptionConstants.DATA_WRITE_FAIL_MSG_US);
        }
        return result;
    }

    @Transactional(value = "transactionManager", rollbackFor = Exception.class)
    public int updateRetailRecord(JSONObject obj, HttpServletRequest request) throws Exception {
        RetailRecord retailRecord = JSONObject.parseObject(obj.toJSONString(), RetailRecord.class);
        retailRecord.setUploadFlag("0");
        int result = 0;
        String lanCode = systemConfigService.getLanCode();
        try {
            result = retailRecordMapper.updateByPrimaryKeySelective(retailRecord);
            logService.insertLog("收银员上班",
                    new StringBuffer(BusinessConstants.LOG_OPERATION_TYPE_EDIT).append(retailRecord.getStartTime()).toString(), request);
        } catch (Exception e) {
            logger.error("异常码[{}],异常提示[{}],异常[{}]",
                    ExceptionConstants.DATA_WRITE_FAIL_CODE, "zh".equals(lanCode) ? ExceptionConstants.DATA_WRITE_FAIL_MSG : ExceptionConstants.DATA_WRITE_FAIL_MSG_US, e);
            throw new BusinessRunTimeException(ExceptionConstants.DATA_WRITE_FAIL_CODE,
                    "zh".equals(lanCode) ? ExceptionConstants.DATA_WRITE_FAIL_MSG : ExceptionConstants.DATA_WRITE_FAIL_MSG_US);
        }
        return result;
    }

    @Transactional(value = "transactionManager", rollbackFor = Exception.class)
    public int deleteRetailRecord(String id, HttpServletRequest request) throws Exception {
//        return batchDeleteRetailRecordByIds(id);
        return 0;
    }

    @Transactional(value = "transactionManager", rollbackFor = Exception.class)
    public int batchDeleteRetailRecord(String ids, HttpServletRequest request) throws Exception {
//        return batchDeleteRetailRecordByIds(ids);
        return 0;
    }

    public int checkIsNameExist(String id, String name) throws Exception {
        RetailRecordExample example = new RetailRecordExample();
        example.createCriteria().andCashieridEqualTo(id).andDeleteFlagNotEqualTo(BusinessConstants.DELETE_FLAG_DELETED);
        List<RetailRecord> list = null;
        String lanCode = systemConfigService.getLanCode();
        try {
            list = retailRecordMapper.selectByExample(example);
        } catch (Exception e) {
            logger.error("异常码[{}],异常提示[{}],异常[{}]",
                    ExceptionConstants.DATA_READ_FAIL_CODE, "zh".equals(lanCode) ? ExceptionConstants.DATA_READ_FAIL_MSG : ExceptionConstants.DATA_READ_FAIL_MSG_US, e);
            throw new BusinessRunTimeException(ExceptionConstants.DATA_READ_FAIL_CODE,
                    "zh".equals(lanCode) ? ExceptionConstants.DATA_READ_FAIL_MSG : ExceptionConstants.DATA_READ_FAIL_MSG_US);
        }
        return list == null ? 0 : list.size();
    }

    @Transactional(value = "transactionManager", rollbackFor = Exception.class)
    public void batchUpdateStatus(String ids, String deleteFlag) throws Exception {
        List<String> idList = StringUtil.strToStringList(ids);
        RetailRecord retailRecord = new RetailRecord();
        retailRecord.setDeleteFlag(deleteFlag);
        RetailRecordExample example = new RetailRecordExample();
        example.createCriteria().andIdIn(idList);
        String lanCode = systemConfigService.getLanCode();
        try {
            retailRecordMapper.updateByExampleSelective(retailRecord, example);
        } catch (Exception e) {
            logger.error("异常码[{}],异常提示[{}],异常[{}]",
                    ExceptionConstants.DATA_WRITE_FAIL_CODE, "zh".equals(lanCode) ? ExceptionConstants.DATA_WRITE_FAIL_MSG : ExceptionConstants.DATA_WRITE_FAIL_MSG_US, e);
            throw new BusinessRunTimeException(ExceptionConstants.DATA_WRITE_FAIL_CODE,
                    "zh".equals(lanCode) ? ExceptionConstants.DATA_WRITE_FAIL_MSG : ExceptionConstants.DATA_WRITE_FAIL_MSG_US);
        }
    }

    public void insertByUser(User user){
        RetailRecordEx record=new RetailRecordEx();
        record.setId(IdUtils.getUUID());
        record.setCashierid(user.getId());
        record.setStartTime(new Date());
        record.setTenantId(user.getTenantId());
        record.setUploadFlag("0");
        retailRecordMapper.insertSelective(record);
    }

    public Map<String, Object> getByIdWithStartTime(HttpServletRequest request) throws Exception {
        Map<String, Object> map = new HashMap<>();
        Map<String, Object> payList = new HashMap<>();
        long time1 = System.currentTimeMillis();
        String userId = userService.getUserId(request);
        RetailRecordEx recordEx = retailRecordMapperEx.getByIdWithStartTime(userId);
        if (recordEx != null) {
            if (recordEx.getStartTime()!=null){
                recordEx.setStartTimeStr(Tools.getCenternTime(recordEx.getStartTime()));
            }
            payList.put("cash_amount",recordEx.getRmbpay());
            map.put("cash_box",recordEx.getCashBox());
            map.put("cashier_name",recordEx.getCashierName());
            List<Map<String, Object>> goodsList=new ArrayList<Map<String, Object>>();
            List<Map<String, Object>> list = retailRecordMapperEx.selectGoodsInfoByUserId(userId,recordEx.getStartTimeStr());
            BigDecimal sumPrice = new BigDecimal("0.00");
            Map<String, Object> all_money=new HashMap<>();
            Map<String, Object> sumSellPrice=new HashMap<>();
            if (list != null && list.size() > 0) {
                for (Map<String, Object> entry : list) {
                    BigDecimal allPrice=(BigDecimal)entry.get("all_money");
                    sumPrice=sumPrice.add(allPrice);
                    Map<String, Object> goods=new HashMap<>();
                    String category_id = (String)entry.get("category_id");
                    if (StringUtils.isNotEmpty(category_id)){
                        MaterialCategory category = materialCategoryMapper.selectByPrimaryKey(category_id);
                        goods.put("class_name",category.getName());
                    }else {
                        goods.put("class_name",null);
                    }
                    entry.put("before_money",allPrice);
                    goods.put("goods",new Map[]{entry});
                    goods.put("goods_id",new String[]{(String) entry.get("goods_id")});
                    goodsList.add(goods);
                }
            }
            all_money.put("all_money",sumPrice);
            all_money.put("before_money",sumPrice);
            sumSellPrice.put("sql_getSell","");
            sumSellPrice.put("sql_time_getGroupSelect","");
            sumSellPrice.put("sumSellPrice",all_money);
            map.put("getSellData",sumSellPrice);
            map.put("goodsList",goodsList);
            long time2 = System.currentTimeMillis();
            map.put("mini_time",(time1-time2)/1000);
            map.put("msg","zh".equals(systemConfigService.getLanCode()) ? "统计数据获取成功" : "Statistics obtained successfully");
            map.put("payList",payList);
            map.put("record_time",recordEx.getStartTimeStr()+"～"+Tools.getCenternTime(new Date()));
            map.put("status",1);
            map.put("store_name",recordEx.getStoreName());
            map.put("sumSellPrice","{}");
        }else {
            map.put("msg","zh".equals(systemConfigService.getLanCode()) ? "查询当前收银员交班信息失败" : "Failed to query the current cashier's shift information");
            map.put("status",0);
        }
        return map;
    }
    public Map<String, Object> getCashboxChangeRecord(JSONObject jsonObject,HttpServletRequest request) throws Exception {
        Map<String, Object> map = new HashMap<>();
        String userId = userService.getUserId(request);
        RetailRecordEx recordEx = retailRecordMapperEx.getByIdWithStartTime(userId);
        Integer page = jsonObject.getInteger("page");
        Integer limit = jsonObject.getInteger("limit");
        Integer type = jsonObject.getInteger("type");
        if (recordEx != null) {
            if (recordEx.getStartTime()!=null){
                recordEx.setStartTimeStr(Tools.getCenternTime(recordEx.getStartTime()));
            }
            List<Map<String, Object>> list = retailRecordMapperEx.selectCashBoxByRecordId(recordEx.getId(), type, (page - 1) * limit, limit);
            if (list != null && list.size() > 0) {
                for (Map<String, Object> entry : list) {
                    entry.put("add_time",Tools.getCenternTime((Date)entry.get("add_time")));
                    entry.put("type_name",entry.get("type").equals(1) ?"增加":"减少");
                }
            }
            Long count = retailRecordMapperEx.countCashBoxByRecordId(recordEx.getId(), type);
            map.put("cashMoney",recordEx.getCashBox());
            map.put("msg","zh".equals(systemConfigService.getLanCode()) ? "获取成功" : "get success");
            map.put("list",list);
            map.put("count",count);
            map.put("timeArr",recordEx.getStartTimeStr()+"～"+Tools.getCenternTime(new Date()));
            map.put("status",1);
        }else {
            map.put("msg","zh".equals(systemConfigService.getLanCode()) ? "查询当前收银员交班信息失败" : "Failed to query the current cashier's shift information");
            map.put("status",0);
        }
        return map;
    }
    public Map<String, Object> changeCashbox(JSONObject jsonObject,HttpServletRequest request) throws Exception {
        Map<String, Object> map = new HashMap<>();
        BigDecimal edit_money = jsonObject.getBigDecimal("edit_money");
        if (null!=edit_money && edit_money.compareTo(BigDecimal.ZERO) <0) {
            map.put("msg","zh".equals(systemConfigService.getLanCode()) ? "缺少必要参数" : "Missing required parameter");
            map.put("status",0);
            return map;
        }
        Integer type = jsonObject.getInteger("type");
        if (type==null){
            map.put("msg","zh".equals(systemConfigService.getLanCode()) ? "缺少必要参数" : "Missing required parameter");
            map.put("status",0);
            return map;
        }
        String remark = jsonObject.getString("remark");
        String userId = userService.getUserId(request);
        RetailRecordEx recordEx = retailRecordMapperEx.getByIdWithStartTime(userId);
        if (recordEx!=null){
            switch (type){
                case 1:
                    recordEx.setCashBox(recordEx.getCashBox().add(edit_money));
                    break;
                case 2:
                    recordEx.setCashBox(recordEx.getCashBox().subtract(edit_money));
                    break;
                default:
                    map.put("msg","zh".equals(systemConfigService.getLanCode()) ? "错误的修改类型" : "wrong modification type");
                    map.put("status",0);
                    return map;
            }
            recordEx.setUploadFlag("0");
            retailRecordMapper.updateByPrimaryKeySelective(recordEx);
            CashBoxRecord record = new CashBoxRecord();
            record.setId(IdUtils.getUUID());
            record.setRecordId(recordEx.getId());
            record.setOperateId(userId);
            record.setType(type);
            record.setEditMoney(edit_money);
            record.setAddTime(new Date());
            record.setRemark(remark);
            record.setUploadFlag("0");
            cashBoxRecordMapper.insertSelective(record);
            map.put("msg","zh".equals(systemConfigService.getLanCode()) ? "钱箱金额修改成功" : "The amount of the cash box has been modified successfully");
            map.put("status",1);
        }else {
            map.put("msg","zh".equals(systemConfigService.getLanCode()) ? "查询当前收银员交班信息失败" : "Failed to query the current cashier's shift information");
            map.put("status",0);
        }
        return map;
    }

    public Map<String, Object> submitWork(HttpServletRequest request) throws Exception {
        int i=0;
        Map<String, Object> map = new HashMap<>();
        String userId = userService.getUserId(request);
        RetailRecordEx recordEx = retailRecordMapperEx.getByIdWithStartTime(userId);
        if (recordEx != null) {
            if (recordEx.getEndTime()!=null){
                map.put("msg","zh".equals(systemConfigService.getLanCode()) ? "当前收银员未上班" : "Current cashier not working");
                map.put("status",0);
                return map;
            }
            recordEx.setEndTime(new Date());
            recordEx.setUploadFlag("0");
            i = retailRecordMapper.updateByPrimaryKeySelective(recordEx);
            if (i>0){
                map.put("msg","zh".equals(systemConfigService.getLanCode()) ? "交班成功" : "Successful shift");
                map.put("status",1);
                redisService.deleteObjectBySession(request,"userId");
            }else {
                map.put("msg","zh".equals(systemConfigService.getLanCode()) ? "交班失败" : "Failed to hand over");
                map.put("status",0);
            }
        }else {
            map.put("msg","zh".equals(systemConfigService.getLanCode()) ? "当前收银员未上班" : "Current cashier not working");
            map.put("status",0);
            return map;
        }
        return map;
    }

    public Map<String, Object> initCashBox(JSONObject jsonObject,HttpServletRequest request) throws Exception {
        int i=0;
        Map<String, Object> map = new HashMap<>();
        BigDecimal cash_box = jsonObject.getBigDecimal("cash_box");
        String userId = userService.getUserId(request);
        RetailRecordEx recordEx = retailRecordMapperEx.getByIdWithStartTime(userId);
        if (recordEx != null) {
            recordEx.setCashBox(cash_box);
            recordEx.setCashBoxStart(cash_box);
            recordEx.setUploadFlag("0");
            i = retailRecordMapper.updateByPrimaryKeySelective(recordEx);
            if (i>0){
                map.put("msg","zh".equals(systemConfigService.getLanCode()) ? "钱箱初始金额设置成功" : "The initial amount of the cash box is set successfully");
                map.put("status",1);
            }else {
                map.put("msg","zh".equals(systemConfigService.getLanCode()) ? "钱箱初始金额设置失败" : "Failed to set initial amount of cash drawer");
                map.put("status",1);
            }
        }else {
            map.put("msg","zh".equals(systemConfigService.getLanCode()) ? "当前收银员未上班" : "Current cashier not working");
            map.put("status",1);
            return map;
        }
        return map;
    }
}
